/**
* 版权声明：厦门睿商网络科技有限公司 版权所有 违者必究
* 日    期：2020-02-20
*/
package com.rzico.order.service;

import com.alibaba.fastjson.JSON;
import com.rzico.account.entity.Transfer;
import com.rzico.account.entity.Payable;
import com.rzico.account.service.TransferService;
import com.rzico.account.service.PayableService;
import com.rzico.base.BaseMapper;
import com.rzico.base.impl.BaseServiceImpl;
import com.rzico.basics.entity.Enterprise;
import com.rzico.basics.entity.Member;
import com.rzico.basics.entity.Product;
import com.rzico.basics.service.EnterpriseService;
import com.rzico.basics.service.ProductService;
import com.rzico.core.entity.SysUser;
import com.rzico.core.service.SysSequenceService;
import com.rzico.core.service.SysUserService;
import com.rzico.exception.CustomException;
import com.rzico.order.entity.*;
import com.rzico.util.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.rzico.order.mapper.PurchaseMapper;
import org.springframework.transaction.annotation.Transactional;
import com.rzico.order.enumx.*;

import java.math.BigDecimal;
import java.util.*;

/**
 * <pre>
 * 采购单业务类
 * </pre>
 *
 * @author Rzico Boot
 * @version 1.0
 */
@Service
public class PurchaseService extends BaseServiceImpl<Purchase, String> {

    @Autowired
    private PurchaseMapper purchaseMapper;

    @Autowired
    private PurchaseItemService purchaseItemService;

    @Autowired
    private EnterpriseService enterpriseService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private PayableService payableService;

    @Autowired
    private ProductService productService;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private WarehouseItemService warehouseItemService;

    @Autowired
    private WarehouseStockService warehouseStockService;

    @Override
    public BaseMapper<Purchase, String> getMapper() {
        return purchaseMapper;
    }

    @Transactional(rollbackFor = Exception.class)
    public int insertPurchase(Purchase purchase){
        Enterprise enterprise = enterpriseService.getCurrent();
        purchase.setEnterpriseId(enterprise.getId());

        BigDecimal amountPayable = purchase.calculateAmountPayable();
        BigDecimal subPrice = purchase.calculateSubPrice();
        BigDecimal subQuantity = purchase.calculateSubQuantity();
        if (amountPayable.compareTo(purchase.getAmountPayable()) != 0){
            throw new CustomException("采购单应付金额被篡改");
        }
        if (subPrice.compareTo(purchase.getSubPrice()) != 0){
            throw new CustomException("采购单商品金额被篡改");
        }
        if (subQuantity.compareTo(purchase.getSubQuantity()) != 0){
            throw new CustomException("采购单商品数量被篡改");
        }
        purchase.setAmountPayable(amountPayable);
        purchase.setSubPrice(subPrice);
        purchase.setSubQuantity(subQuantity);
        purchase.setOrderStatus(0);
        purchase.setShippingStatus(0);
        if (null == purchase.getPaymentStatus()){
            purchase.setPaymentStatus(0);
        }
        if (null == purchase.getFreight()){
            purchase.setFreight(new BigDecimal(0));
        }
        if (null == purchase.getOffsetAmount()){
            purchase.setOffsetAmount(new BigDecimal(0));
        }
        purchase.setDeleted(false);

        if (null == purchase.getTaxType()){
            purchase.setTaxType(0);
        }
        purchase.setTax(BigDecimal.ZERO);
        SysUser sysUser = sysUserService.getCurrent();
        purchase.setOperatorId(sysUser.getId());
        List<PurchaseItem> itemsList = new ArrayList<>();
        for (PurchaseItem purchaseItem : purchase.getItemList()){
            initOrderItem(purchaseItem);
            itemsList.add(purchaseItem);
        }
        purchase.setItemList(itemsList);
        return insertUseGeneratedKeys(purchase);
    }

    private void initOrderItem(PurchaseItem orderItem){

        Product product = productService.selectByPrimaryKey(orderItem.getProductId());
        orderItem.setSn(product.getSn());
        orderItem.setCost(product.getCost());
        orderItem.setName(product.getName());
        if (product.getSpec1()==null) {
            product.setSpec1("");
        }
        if (product.getSpec2()==null) {
            product.setSpec2("");
        }
        orderItem.setSpec(product.getSpec1()+product.getSpec2());
        orderItem.setUnit(product.getUnit());
        orderItem.setWeight(product.getWeight());
        orderItem.setThumbnail(product.getThumbnail());

        if (null == orderItem.getReturnQuantity()){
            orderItem.setReturnQuantity(BigDecimal.ZERO);
        }
        if (null == orderItem.getStockQuantity()){
            orderItem.setStockQuantity(BigDecimal.ZERO);
        }

        if (null == orderItem.getDiscount()){
            orderItem.setDiscount(BigDecimal.ZERO);
        }


    }
    @Transactional(rollbackFor = Exception.class)
    public int update(Purchase purchase){
        //1、查询原订单信息
        Purchase sourceOrder = purchaseMapper.selectByPrimaryKey(purchase.getId());
        if (null == sourceOrder){
            throw new CustomException("订单不存在");
        }
        if (0 != sourceOrder.getOrderStatus()){
            throw new CustomException("订单已不可修改");
        }
        //2、计算订单金额，更新订单主表
        int affectCount = purchaseMapper.updateByPrimaryKeySelective(purchase);
        if (affectCount > 0){
            /**
             * 3、原订单商品明细与编辑之后的商品明细对比
             * result = 0, insert
             * result = 1, update
             * result = 2, delete
             */
            PurchaseItem paramsItem = new PurchaseItem();
            paramsItem.setPurchaseId(sourceOrder.getId());
            List<PurchaseItem> sourceOrderItemList = purchaseItemService.select(paramsItem);
            List<PurchaseItem> targetOrderItemList = purchase.getItemList();
            for (PurchaseItem targetOrderItem : targetOrderItemList){
                if (targetOrderItem.getId()==null) {
                    initOrderItem(targetOrderItem);
                    targetOrderItem.setPurchaseId(purchase.getId());
                    purchaseItemService.insertUseGeneratedKeys(targetOrderItem);
                } else {
                    for (PurchaseItem sourceOrderItem : sourceOrderItemList){
                        if (targetOrderItem.getId().equals(sourceOrderItem.getId())){
                            sourceOrderItemList.remove(sourceOrderItem);
                            break;
                        }
                    }
                    purchaseItemService.updateByPrimaryKeySelective(targetOrderItem);
                }
            }
            //4、删除未匹配中的数据
            if (null != sourceOrderItemList && sourceOrderItemList.size() > 0){
                for (PurchaseItem orderItem : sourceOrderItemList){
                    purchaseItemService.deleteByPrimaryKey(orderItem.getId());
                }
            }
        }
        return affectCount;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertUseGeneratedKeys(Purchase purchase) {
        int affectCount = super.insertUseGeneratedKeys(purchase);
        if (affectCount > 0){
            for (PurchaseItem purchaseItem : purchase.getItemList()){
                purchaseItem.setPurchaseId(purchase.getId());
            }
            purchaseItemService.insertUseGeneratedKeyList(purchase.getItemList());
        }
        return affectCount;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByIds(Object[] ids) {
        int rw = 0;
        for (Object id:ids) {
            Purchase purchase = selectByPrimaryKey(id);
            purchase.setDeleted(true);
            rw = rw + super.updateByPrimaryKeySelective(purchase);
        }
        return rw;
    }

    /**
     * 订单确认
     * @param purchase
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int confirm(Purchase purchase) {
        Purchase purchaseConfirm = selectByPrimaryKey(purchase.getId());
        if (null == purchaseConfirm){
            throw new CustomException("尚未查询到采购单");
        }
        purchaseConfirm.setOrderStatus(PurchaseOrderStatusEnum.ORDER_STATUS_CONFIRM.getId());
        purchaseConfirm.setOrderDate(new Date());
        int affectCount = super.updateByPrimaryKeySelective(purchaseConfirm);
        if (affectCount > 0){
            //todo 应付账款
            Long payableId = null;
            int result = purchaseConfirm.getAmountPayable().abs().compareTo(purchaseConfirm.getAmountPaid().abs());
            if (result == 1){
                Payable payable = new Payable();
                payable.setAmount(purchaseConfirm.getAmountPayable());
                payable.setAmountPaid(purchaseConfirm.getAmountPaid());
                payable.setType(0);
                payable.setDeleted(false);
                payable.setSupplierId(purchaseConfirm.getSupplierId());
                payable.setEnterpriseId(purchaseConfirm.getEnterpriseId());
                payable.setOrderId(purchaseConfirm.getId());
                payable.setOrderType(0);
                payable.setOrderSn(purchaseConfirm.getSn());
                payable.setOfficeId(purchaseConfirm.getOfficeId());
                int num = purchaseConfirm.getAmountPaid().compareTo(BigDecimal.ZERO);
                if (num == 0){
                    //订单未付款
                    payable.setStatus(0);
                }else {
                    //订单部分付款
                    payable.setStatus(1);
                }
                payableService.insertUseGeneratedKeys(payable);
                payableId = payable.getId();
            }
            //todo 已付金额大于0，生成付款记录
      /*      if (purchaseConfirm.getAmountPaid().compareTo(BigDecimal.ZERO) > 0){
                this.insertBuying(purchaseConfirm, payableId);
            }*/
        }
        return affectCount;
    }

    /**
     * 付款单
     * @return
     */
/*    public int insertBuying(Purchase purchase, Long payableId){
        Transfer buying = new Transfer();
        buying.setSn(sysSequenceService.generate("order"));
        buying.setAmount(purchase.getAmountPaid());
        //todo 暂时写死，待改
        buying.setPaymentPluginId(purchase.getPaymentPluginId());
        buying.setPaymentDate(new Date());
        buying.setEmployeeId(purchase.getCreateBy());
        buying.setSupplierId(purchase.getSupplierId());
        buying.setPayableId(payableId);
        buying.setType(0);
        buying.setDeleted(false);
        if (null != payableId){
            buying.setPayableId(payableId);
        }
        buying.setEnterpriseId(purchase.getEnterpriseId());
        return buyingService.insertUseGeneratedKeys(buying);
    }*/
    /**
     * 分批审核入库，入库单审核通过会更新商品明细的入库数量
     * 本次入库数量StockQuantity字段存储
     * @param orderId
     * @param itemList
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Warehouse batchInStock(Long orderId, Long shopId, String sn, Date orderDate, List<PurchaseItem> itemList){
        SysUser sysUser = sysUserService.getCurrent();
        //1、检查销售订单是否存在
        Warehouse warehouse = null;
        Purchase purchase = selectByPrimaryKey(orderId);
        if (null == purchase){
            throw new CustomException("未查找到订单");
        }

        //2、检查发货数量，并封装需要保存的orderItemList
        String errMsg = "";
        BigDecimal shippingQuantity = BigDecimal.ZERO;
        for (PurchaseItem paramItem : itemList){
            PurchaseItem target = purchaseItemService.selectByPrimaryKey(paramItem.getId());
            //可发货数量
            BigDecimal canShippingQuantity = target.getAvailableStockQuantity();// target.getQuantity().subtract(target.getStockQuantity());
            if (canShippingQuantity.compareTo(BigDecimal.ZERO)<0) {
                canShippingQuantity = BigDecimal.ZERO;
            }
            //可发货数量与前端传过来的发货数量对比
            int result = canShippingQuantity.compareTo(paramItem.getStockQuantity());
            if (result < 0){
                errMsg = "发货数量大于可发货数量";
                break;
            }
            //计算优惠金额
            if (paramItem.getStockQuantity().compareTo(target.getQuantity())==0) {
                paramItem.setDiscount(target.getDiscount());
            } else {
                paramItem.setDiscount(target.getDiscount().multiply(paramItem.getStockQuantity()).divide(target.getQuantity(), 2, BigDecimal.ROUND_HALF_DOWN));
            }

            shippingQuantity = shippingQuantity.add(target.getStockQuantity().add(paramItem.getStockQuantity()));
        }
        if (StringUtils.isNotEmpty(errMsg)){
            throw new CustomException(errMsg);
        }
        //3、更新order的shippingStatus状态,检查状态是否发货完毕
        if (shippingQuantity.compareTo(purchase.getSubQuantity())>=0) {
            purchase.setShippingStatus(OrderShippingStatusEnum.SHIPPING_STATUS_SHIPPNG.getId());
        }
        purchase.setModifyBy(sysUser.getId());
        int affectCount = updateByPrimaryKeySelective(purchase);
        if (affectCount > 0){
            for (PurchaseItem target : itemList){
                target.setQuantity(target.getStockQuantity());
            }

            //4、生成出库单
            purchase.setItemList(itemList);
            //使用前端手动选择的shopId出库
            purchase.setShopId(shopId);
            purchase.setOrderDate(orderDate);
            warehouse = this.insertWarehouse(purchase, sn, WarehouseTypeEnum.WAREHOUSE_TYPE_PURCHASE_IN.getId(), purchase.getSn());

        }
        return warehouse;
    }


    @Transactional(rollbackFor = Exception.class)
    public int inStockAndAudit(Long orderId, Long shopId, String sn, Date orderDate, List<PurchaseItem> itemList){
        Warehouse warehouse = batchInStock(orderId, shopId, sn, orderDate, itemList);
        return warehouseService.audit(warehouse.getId());
    }

    /**
     * 分批退货单
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int batchOutStock(Long id, Long shopId,String sn, Date orderDate, List<PurchaseItem> itemList) {
        SysUser sysUser = sysUserService.getCurrent();
        //1、检查销售订单是否存在
        Purchase purchase = selectByPrimaryKey(id);
        if (null == purchase){
            throw new CustomException("未查找到订单");
        }

        //2、检查退货数量，并封装需要保存的orderItemList
        String errMsg = "";
        BigDecimal returnQuantity = BigDecimal.ZERO;
        BigDecimal shippingQuantity = BigDecimal.ZERO;
        for (PurchaseItem paramItem : itemList){
            PurchaseItem target = purchaseItemService.selectByPrimaryKey(paramItem.getId());
            //可退货数量 = 已入库数量 - 本次要退货数量
            BigDecimal canReturnQuantity = target.getQuantity().subtract(target.getReturnQuantity());
            if (canReturnQuantity.compareTo(BigDecimal.ZERO)<0) {
                canReturnQuantity = BigDecimal.ZERO;
            }
            //可退货数量与前端传过来的退货数量对比
            int result = canReturnQuantity.compareTo(paramItem.getReturnQuantity());
            if (result < 0){
                errMsg = "退货数量大于可退货数量";
                break;
            }
            //计算优惠金额
            if (paramItem.getStockQuantity().compareTo(target.getQuantity())==0) {
                paramItem.setDiscount(target.getDiscount());
            } else {
                paramItem.setDiscount(target.getDiscount().multiply(paramItem.getStockQuantity()).divide(target.getQuantity(), 2, BigDecimal.ROUND_HALF_DOWN));
            }

            shippingQuantity = shippingQuantity.add(target.getStockQuantity());
            returnQuantity = returnQuantity.add(target.getReturnQuantity().add(paramItem.getReturnQuantity()));
        }
        if (StringUtils.isNotEmpty(errMsg)){
            throw new CustomException(errMsg);
        }
        //3、更新order的shippingStatus状态
        if (shippingQuantity.compareTo(returnQuantity)<=0) {
            purchase.setShippingStatus(PurchaseShippingStatusEnum.SHIPPING_STATUS_REFUND_SHIPPING.getId());
        }
        purchase.setModifyBy(sysUser.getId());
        int affectCount = updateByPrimaryKeySelective(purchase);
        if (affectCount > 0) {
            for (PurchaseItem target : itemList){
                target.setQuantity(target.getReturnQuantity());
            }
            //4、生成入库单
            purchase.setItemList(itemList);
            //使用前端手动选择的shopId出库
            purchase.setShopId(shopId);
            purchase.setOrderDate(DateUtils.truncate(orderDate,Calendar.DATE));
            this.insertWarehouse(purchase, sn, WarehouseTypeEnum.WAREHOUSE_TYPE_PURCHASE_OUT.getId(), purchase.getSn());
        }
        return affectCount;
    }


/*    @Transactional(rollbackFor = Exception.class)
    public int disAudit(Long id){
        //1、判断单据是否存在
        Purchase purchase = selectByPrimaryKey(id);
        if (null == purchase){
            throw new CustomException("采购单不存在");
        }
        //2、非已完成不可弃审
        if (!purchase.getOrderStatus().equals(PurchaseOrderStatusEnum.ORDER_STATUS_COMPLETE.getId())){
            throw new CustomException("单据状态非已完成,不可弃审!");
        }
        //3、更新单据状态，并回滚入库单状态
        purchase.setOrderStatus(PurchaseOrderStatusEnum.ORDER_STATUS_CONFIRM.getId());
        int affectCount = super.updateByPrimaryKeySelective(purchase);
        if (affectCount > 0){
            Warehouse params = new Warehouse();
            params.setOrderId(purchase.getId());
            params.setWarehouseType(WarehouseTypeEnum.WAREHOUSE_TYPE_PURCHASE_IN.getId());
            List<Warehouse> warehouseList = warehouseService.select(params);
            if (null != warehouseList && warehouseList.size() >0){
                for (Warehouse warehouse : warehouseList){
                    //出库单“已完成”状态，需要更新出库单状态和回滚库存数量，防止手动弃审里出库单回滚了库存，这里再次回滚库存
                    if (warehouse.getStatus().equals(WarehouseStatusEnum.WAREHOUSE_STATUS_COMPLETE.getId())){
                        //更新出库单从“已完成”到“已确认”
                        warehouse.setStatus(WarehouseStatusEnum.WAREHOUSE_STATUS_CONFIRM.getId());
                        warehouseService.updateByPrimaryKeySelective(warehouse);
                        //回滚出库单的库存
                        WarehouseItem wareItem = new WarehouseItem();
                        wareItem.setWarehouseId(warehouse.getId());
                        List<WarehouseItem> list = warehouseItemService.select(wareItem);
                        for (WarehouseItem warehouseItem : list){
                            warehouseStockService.preCancelHandle(warehouse.getWarehouseType(), warehouseItem);
                        }
                    }

                }
            }else {
                throw new CustomException("采购单尚未查找到对应的出入库单，请核对");
            }
        }
        return affectCount;
    }*/


    @Transactional(rollbackFor = Exception.class)
    public int cancel(Long id){
        int affectCount = 0;
        //1、判断单据是否存在
        Purchase purchase = selectByPrimaryKey(id);
        if (null == purchase){
            throw new CustomException("采购单不存在");
        }

        SysUser sysUser = sysUserService.getCurrent();
        Boolean isAdmin = sysUserService.isAdmin(sysUser);
        if (!isAdmin){
            if (!sysUser.getId().equals(purchase.getCreateBy())){
                throw new CustomException("当前人员非制单人员");
            }
        }

        //2、非已确认，不可作废
        if (purchase.getOrderStatus().equals(WarehouseStatusEnum.WAREHOUSE_STATUS_COMPLETE.getId())){
            throw new CustomException("采购单已完成，不可作废");
        }else if (purchase.getOrderStatus().equals(WarehouseStatusEnum.WAREHOUSE_STATUS_CONFIRM.getId())){
            //已确认的订单，需要判断应收账款
            Payable param = new Payable();
            param.setOrderId(purchase.getId());
            List<Payable> list = payableService.select(param);
            if (null != list && list.size() >0){
                Boolean result = true;
                for (Payable payable : list){
                    if (!payable.getStatus().equals(0)){
                        result = false;
                        break;
                    }
                }
                if (!result){
                    throw new CustomException("采购单有已支付应付账款,不可作废");
                }
                //删除应付账款
                for (Payable payable : list){
                    payable.setDeleted(true);
                    payableService.updateByPrimaryKeySelective(payable);
                }
            }

            //3、更新单据状态，并处理库存数据
            purchase.setOrderStatus(PurchaseOrderStatusEnum.ORDER_STATUS_CANCLE.getId());
            affectCount = super.updateByPrimaryKeySelective(purchase);
            if (affectCount > 0){
                Warehouse params = new Warehouse();
                params.setOrderId(purchase.getId());
                List<Warehouse> warehouseList = warehouseService.select(params);
                if (null != warehouseList && warehouseList.size() >0){
                    for (Warehouse warehouse : warehouseList){
                        //更新出库单从“已确认”到“已取消”
                        warehouse.setStatus(WarehouseStatusEnum.WAREHOUSE_STATUS_CANCEL.getId());
                        warehouseService.updateByPrimaryKeySelective(warehouse);
                        //回滚出库单的库存
                        WarehouseItem wareItem = new WarehouseItem();
                        wareItem.setWarehouseId(warehouse.getId());
                        List<WarehouseItem> warehouseItemList = warehouseItemService.select(wareItem);
                        for (WarehouseItem warehouseItem : warehouseItemList){
                            warehouseStockService.afterCancelCompletion(warehouse.getWarehouseType(), warehouseItem);
                        }
                    }
//                }else {
//                    throw new CustomException("采购单尚未查找到对应的出入库单，请核对");
                }
            }


        }else{
            //未确认的采购单，直接作废，不需要操作应付账款和库存
            purchase.setOrderStatus(PurchaseOrderStatusEnum.ORDER_STATUS_CANCLE.getId());
            affectCount = super.updateByPrimaryKeySelective(purchase);
        }
        return affectCount;
    }

    /**
     * 生成出入库
     * @param purchase
     */
    @Transactional(rollbackFor = Exception.class)
    public Warehouse insertWarehouse(Purchase purchase,String sn, Integer warehouseType, String orderSn){
        SysUser sysUser = sysUserService.getCurrent();
        Warehouse warehouse = new Warehouse();
        warehouse.setSn(sn);
        warehouse.setWarehouseType(warehouseType);
        warehouse.setStatus(0);
        warehouse.setOrderDate(DateUtils.truncate(purchase.getOrderDate(), Calendar.DATE));
        warehouse.setTaxType(purchase.getTaxType());
        warehouse.setSupplierId(purchase.getSupplierId());
        //采购单的入库单会员默认是供应商
        warehouse.setMemberId(purchase.getSupplierId());
        warehouse.setOrderId(purchase.getId());
        warehouse.setEnterpriseId(purchase.getEnterpriseId());
        warehouse.setShopId(purchase.getShopId());
        warehouse.setDeleted(false);
        warehouse.setOfficeId(purchase.getOfficeId());
        warehouse.setOperatorId(sysUser.getId());
        warehouse.setSPrint(0);
        warehouse.setOrderSn(orderSn);
        //明细表数据
        List<WarehouseItem> itemsList = new ArrayList<>();
        for (PurchaseItem purchaseItem : purchase.getItemList()){

            WarehouseItem warehouseItem = new WarehouseItem();
            warehouseItem.setCost(purchaseItem.getCost());
            warehouseItem.setName(purchaseItem.getName());
            warehouseItem.setPrice(purchaseItem.getPrice());
            //重点：这里的数量，是采购单当前入库的数量，使用CurrentQuantity字段  zzm 2020-04-06 23:33:20
            warehouseItem.setQuantity(purchaseItem.getQuantity());
            warehouseItem.setSn(purchaseItem.getSn());
            warehouseItem.setSpec(purchaseItem.getSpec());
            warehouseItem.setUnit(purchaseItem.getUnit());
            warehouseItem.setDiscount(purchaseItem.getDiscount());
            warehouseItem.setThumbnail(purchaseItem.getThumbnail());
            warehouseItem.setProductId(purchaseItem.getProductId());
            warehouseItem.setWarehouseId(warehouse.getId());

            //冗余存储
            warehouseItem.setShopId(warehouse.getShopId());
            warehouseItem.setEnterpriseId(warehouse.getEnterpriseId());
            warehouseItem.setTax(BigDecimal.ZERO);
            itemsList.add(warehouseItem);
        }
        warehouse.setItemList(itemsList);

        warehouse.setSubPrice(warehouse.calculateSubPrice());
        warehouse.setSubQuantity(warehouse.calculateSubQuantity());

        warehouseService.insertUseGeneratedKeys(warehouse);

        //自动确认
        warehouseService.confirm(warehouse.getId());
        return warehouse;
    }
}
